<template>
  <div
    ref="wrapperRef"
    class="component-wrapper"
    :class="{ selected, dragging }"
    :style="wrapperStyle"
    @mousedown="handleMouseDown"
    @click.stop="handleSelect">
    <!-- 组件内容 -->
    <component
      :is="componentRenderer"
      v-bind="props.component.props"
      :style="componentStyle" />

    <!-- 组件工具栏 -->
    <div class="component-toolbar" v-show="selected">
      <el-button-group>
        <el-button size="small" @click.stop="handleDelete">
          <el-icon><Delete /></el-icon>
        </el-button>
        <el-button size="small" @click.stop="handleDuplicate">
          <el-icon><CopyDocument /></el-icon>
        </el-button>
      </el-button-group>
    </div>

    <!-- 调整大小的手柄 -->
    <template v-if="selected">
      <div class="resize-handle tl" @mousedown.stop="(e) => handleResizeStart(e, 'tl')"></div>
      <div class="resize-handle tr" @mousedown.stop="(e) => handleResizeStart(e, 'tr')"></div>
      <div class="resize-handle bl" @mousedown.stop="(e) => handleResizeStart(e, 'bl')"></div>
      <div class="resize-handle br" @mousedown.stop="(e) => handleResizeStart(e, 'br')"></div>
    </template>

    <!-- 拖动指示器 -->
    <div v-if="dragging" class="drag-indicator"></div>
  </div>
</template>

<script setup>
import { ref, computed, shallowRef, onMounted } from 'vue'
import { Delete, CopyDocument } from '@element-plus/icons-vue'
import { componentRenderers } from '../config/components'
import { v4 as uuidv4 } from 'uuid'

const props = defineProps({
  component: {
    type: Object,
    required: true
  },
  selected: {
    type: Boolean,
    default: false
  }
})

const emit = defineEmits(['select', 'delete', 'update'])

const wrapperRef = ref(null)
const componentRenderer = shallowRef(null)
const dragging = ref(false)
const startPosition = ref({ x: 0, y: 0 })
const currentPosition = ref({ x: 0, y: 0 })

// 包装器样式
const wrapperStyle = computed(() => ({
  position: 'absolute',
  left: `${currentPosition.value.x}px`,
  top: `${currentPosition.value.y}px`,
  width: props.component.style?.width || '200px',
  height: props.component.style?.height || 'auto',
  transform: dragging.value ? `translate(${currentPosition.value.x - startPosition.value.x}px, ${currentPosition.value.y - startPosition.value.y}px)` : 'none',
  zIndex: dragging.value ? 1000 : 1
}))

// 组件样式
const componentStyle = computed(() => ({
  width: '100%',
  height: '100%'
}))

// 拖拽指令
const vDrag = {
  mounted(el) {
    const wrapper = el
    let startX, startY
    let startRect

    const handleMouseDown = (e) => {
      if (e.target.closest('.resize-handle') || !wrapperRef.value) return
      e.preventDefault()
      
      startRect = wrapperRef.value.getBoundingClientRect()
      startX = e.clientX
      startY = e.clientY
      
      document.addEventListener('mousemove', handleMouseMove)
      document.addEventListener('mouseup', handleMouseUp)
    }

    const handleMouseMove = (e) => {
      const parentRect = wrapper.offsetParent.getBoundingClientRect()
      const deltaX = e.clientX - startX
      const deltaY = e.clientY - startY
      
      // 计算相对于父容器的位置
      const left = startRect.left - parentRect.left + deltaX
      const top = startRect.top - parentRect.top + deltaY
      
      // 更新组件位置
      emit('update', {
        ...props.component,
        style: {
          ...props.component.style,
          transform: `translate(${deltaX}px, ${deltaY}px)`,
          position: 'relative',
          left: `${left}px`,
          top: `${top}px`
        }
      })
    }

    const handleMouseUp = () => {
      document.removeEventListener('mousemove', handleMouseMove)
      document.removeEventListener('mouseup', handleMouseUp)
    }

    wrapper.addEventListener('mousedown', handleMouseDown)
  }
}

// 调整大小
const handleResizeStart = (e, handle) => {
  if (!wrapperRef.value) return
  e.preventDefault()
  
  const parentRect = wrapperRef.value.offsetParent.getBoundingClientRect()
  const rect = wrapperRef.value.getBoundingClientRect()
  const startX = e.clientX
  const startY = e.clientY
  const startWidth = rect.width
  const startHeight = rect.height
  const startLeft = rect.left - parentRect.left
  const startTop = rect.top - parentRect.top

  const handleMouseMove = (e) => {
    let newWidth = startWidth
    let newHeight = startHeight
    let newLeft = startLeft
    let newTop = startTop

    const deltaX = e.clientX - startX
    const deltaY = e.clientY - startY

    switch (handle) {
      case 'br':
        newWidth = Math.max(50, startWidth + deltaX)
        newHeight = Math.max(30, startHeight + deltaY)
        break
      case 'bl':
        newWidth = Math.max(50, startWidth - deltaX)
        newLeft = startLeft + deltaX
        newHeight = Math.max(30, startHeight + deltaY)
        break
      case 'tr':
        newWidth = Math.max(50, startWidth + deltaX)
        newHeight = Math.max(30, startHeight - deltaY)
        newTop = startTop + deltaY
        break
      case 'tl':
        newWidth = Math.max(50, startWidth - deltaX)
        newHeight = Math.max(30, startHeight - deltaY)
        newLeft = startLeft + deltaX
        newTop = startTop + deltaY
        break
    }

    emit('update', {
      ...props.component,
      style: {
        ...props.component.style,
        width: `${newWidth}px`,
        height: `${newHeight}px`,
        position: 'relative',
        left: `${newLeft}px`,
        top: `${newTop}px`
      }
    })
  }

  const handleMouseUp = () => {
    document.removeEventListener('mousemove', handleMouseMove)
    document.removeEventListener('mouseup', handleMouseUp)
  }

  document.addEventListener('mousemove', handleMouseMove)
  document.addEventListener('mouseup', handleMouseUp)
}

// 加载组件
const loadComponent = async () => {
  try {
    const renderer = componentRenderers[props.component.type]
    if (renderer) {
      const module = await renderer()
      componentRenderer.value = module.default
    }
  } catch (error) {
    console.error('加载组件失败:', error)
  }
}

// 选择组件
const handleSelect = () => {
  emit('select', props.component)
}

// 删除组件
const handleDelete = () => {
  emit('delete', props.component)
}

// 复制组件
const handleDuplicate = () => {
  const newComponent = {
    ...props.component,
    id: uuidv4()
  }
  emit('update', newComponent)
}

// 处理组件事件
const handleEvent = (event) => {
  if (!event) return
  // TODO: 处理组件事件
  console.log('Component event:', event)
}

// 鼠标按下事件
const handleMouseDown = (e) => {
  if (e.target.closest('.resize-handle') || e.target.closest('.component-toolbar')) return
  e.preventDefault()

  const rect = wrapperRef.value.getBoundingClientRect()
  startPosition.value = {
    x: rect.left,
    y: rect.top
  }
  currentPosition.value = {
    x: rect.left,
    y: rect.top
  }
  dragging.value = true

  document.addEventListener('mousemove', handleMouseMove)
  document.addEventListener('mouseup', handleMouseUp)
}

// 鼠标移动事件
const handleMouseMove = (e) => {
  if (!dragging.value) return

  // 计算新位置
  currentPosition.value = {
    x: e.clientX - (e.clientX - startPosition.value.x),
    y: e.clientY - (e.clientY - startPosition.value.y)
  }

  // 网格对齐
  const gridSize = 10
  currentPosition.value.x = Math.round(currentPosition.value.x / gridSize) * gridSize
  currentPosition.value.y = Math.round(currentPosition.value.y / gridSize) * gridSize

  // 更新组件位置
  emit('update', {
    ...props.component,
    style: {
      ...props.component.style,
      position: 'absolute',
      left: `${currentPosition.value.x}px`,
      top: `${currentPosition.value.y}px`
    }
  })
}

// 鼠标松开事件
const handleMouseUp = () => {
  dragging.value = false
  document.removeEventListener('mousemove', handleMouseMove)
  document.removeEventListener('mouseup', handleMouseUp)
}

onMounted(() => {
  loadComponent()
})
</script>

<style scoped>
.component-wrapper {
  position: absolute;
  padding: 4px;
  border: 2px solid transparent;
  border-radius: 4px;
  background-color: #fff;
  user-select: none;
  cursor: move;
  transition: border-color 0.3s;
}

.component-wrapper.dragging {
  opacity: 0.8;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

.drag-indicator {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  border: 2px dashed var(--el-color-primary);
  pointer-events: none;
  z-index: -1;
}

.drag-handle {
  position: absolute;
  top: 50%;
  left: -20px;
  width: 16px;
  height: 16px;
  transform: translateY(-50%);
  display: none;
  align-items: center;
  justify-content: center;
  color: var(--el-text-color-secondary);
  cursor: move;
}

.component-wrapper:hover .drag-handle {
  display: flex;
}

.drag-guides {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  pointer-events: none;
}

.guide-line {
  position: absolute;
  background-color: var(--el-color-primary);
  opacity: 0.3;
}

.guide-line.horizontal {
  left: 0;
  right: 0;
  height: 1px;
}

.guide-line.vertical {
  top: 0;
  bottom: 0;
  width: 1px;
}

.resize-handle {
  position: absolute;
  width: 8px;
  height: 8px;
  background-color: var(--el-color-primary);
  border: 2px solid white;
  border-radius: 50%;
  z-index: 1;
  opacity: 0;
  transition: opacity 0.3s;
}

.component-wrapper:hover .resize-handle,
.component-wrapper.selected .resize-handle {
  opacity: 1;
}

.component-wrapper {
  padding: 2px;
  border: 2px solid transparent;
  border-radius: 4px;
  transition: border-color 0.3s;
  cursor: move;
  user-select: none;
  will-change: transform;
}

.resize-handle {
  position: absolute;
  width: 8px;
  height: 8px;
  background-color: var(--el-color-primary);
  border: 2px solid white;
  border-radius: 50%;
  z-index: 1;
}

.resize-handle.tl {
  top: -6px;
  left: -6px;
  cursor: nw-resize;
}

.resize-handle.tr {
  top: -6px;
  right: -6px;
  cursor: ne-resize;
}

.resize-handle.bl {
  bottom: -6px;
  left: -6px;
  cursor: sw-resize;
}

.resize-handle.br {
  bottom: -6px;
  right: -6px;
  cursor: se-resize;
}

.component-wrapper:hover {
  border-color: var(--el-color-primary-light-7);
}

.component-wrapper.selected {
  border-color: var(--el-color-primary);
}

.component-toolbar {
  position: absolute;
  top: -32px;
  right: 0;
  padding: 4px;
  background-color: #fff;
  border: 1px solid var(--el-border-color);
  border-radius: 4px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  z-index: 100;
}
</style> 